package org.cosmos.modules.web;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;


/**
 * httpclient工具类
 * 
 * @author fisher
 */
public class SimpleHttpClient {

    private static final Logger logger = LoggerFactory.getLogger(SimpleHttpClient.class);
    private static final String DEFAULT_CHARSET = "UTF-8";
    private int timeout = 20;
    private int poolSize = 20;


    /**
     * 初始化CloseableHttpClient
     */
    private CloseableHttpClient init() {
        // --Set timeout--//
        RequestConfig requestConfig =
                RequestConfig.custom().setSocketTimeout(timeout * 1000).setConnectTimeout(timeout * 1000)
                    .setConnectionRequestTimeout(timeout * 1000).build();
        // --set poolsize ,create httpClient--//
        CloseableHttpClient httpClient =
                HttpClientBuilder.create().setMaxConnTotal(poolSize).setMaxConnPerRoute(poolSize)
                    .setDefaultRequestConfig(requestConfig).build();
        return httpClient;
    }


    /**
     * POST请求
     * 
     * @param url
     *            url地址
     * @param paramMap
     *            url参数
     * @param charset
     *            编码
     * @return response
     */
    public String post(String url, Map<String, String> paramMap, String charset) {
        CloseableHttpClient httpClient = init();
        HttpPost httpPost = new HttpPost(url);
        String body = null;

        try {
            if (paramMap != null && !paramMap.isEmpty()) {
                List<NameValuePair> params = parseFromParamMap(paramMap);
                if (!params.isEmpty()) {
                    httpPost.setEntity(new UrlEncodedFormEntity(params, charset));
                }
            }

            CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity entity = httpResponse.getEntity();

            body = EntityUtils.toString(entity);

            if (entity != null) {
                EntityUtils.consume(entity);
            }
        }
        catch (IOException e) {
            httpPost.abort();
            logger.error("post from remote " + url + "  error", e);
        }
        finally {
            destroy(httpClient);
        }
        return body;
    }


    public String post(String url, Map<String, String> paramMap) {
        return post(url, paramMap, DEFAULT_CHARSET);
    }


    public String post(String url) {
        return post(url, null, DEFAULT_CHARSET);
    }


    private List<NameValuePair> parseFromParamMap(Map<String, String> paramMap) {
        List<NameValuePair> nameValuePairs = Lists.newArrayList();
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {

            String paramName = entry.getKey();
            String paramValue = entry.getValue();

            BasicNameValuePair basicNameValuePair = new BasicNameValuePair(paramName, paramValue);
            nameValuePairs.add(basicNameValuePair);
        }
        return nameValuePairs;
    }


    /**
     * 关闭httpClient
     */
    public void destroy(CloseableHttpClient httpClient) {
        try {
            httpClient.close();
        }
        catch (IOException e) {
            logger.error("httpclient close fail", e);
        }
    }


    public int getTimeout() {
        return timeout;
    }


    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }


    public int getPoolSize() {
        return poolSize;
    }


    public void setPoolSize(int poolSize) {
        this.poolSize = poolSize;
    }

}
